package com.hollycrm.hollysqm.core.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

import javax.annotation.PostConstruct;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.http.client.HttpClient;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.impl.HttpClientUtil;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.hollycrm.hollysqm.core.target.DocColumn;



/**
 * solr工具类，提供访问solr云
 * @author jianglong
 * @date 2017年3月29日 下午3:33:00
 */
@Component //作为组件，在启动服务的时候初始化
//@PropertySource("classpath:configure.properties")
public class SolrUtils {
    /**
     * 日志.
     */
    private static final Logger log = LoggerFactory.getLogger(SolrUtils.class);
    /**
     * 最大连接数.
     */
    private static int maxConnections = 128;
    /**
     * 每个主机的最大连接数.
     */
    private static int maxConnectionsPerHost = 32;
    /**
     * solrClient 用于连接solrCloud.
     */
    private static SolrClient solrClient;
    /**
     * 发送http请求的客户端.
     */
    private static HttpClient httpClient;
    /**
     * zookeeper主机
     */
    @Value("${zkHost}")
    private String zkHost;
    /**
     * 获取solrCloud集合
     */
    @Value("${solr.collection}")
    private String defaultCollection;
    
    /**
     * 通过URL获取solrCloud集合
     */
    @Value("${solr.baseSolrUrl:http://134.203.7.119:8983/solr/hollysqm_2017/}")
    private String baseSolrUrl;
    
    private static String collection;
    private static String host;
    private static String baseUrl;

    @PostConstruct  
    public void init() {  
    	host = zkHost;
    	collection = defaultCollection;
    	baseUrl = baseSolrUrl;
    }
    
    /**
     * 初始化连接
     */
    static { 
        newHttpClient();
    }

    /**
     * 获取solrClient.
     * @return SolrClient
     */
    public static SolrClient getSolrClient() { 
    	if (solrClient==null)
    		solrClient = newSolrClient(host,collection);    	
        return solrClient;
    }
    
    /**
     * 获取solrClient.
     * @return SolrClient
     */
    public static SolrClient getBaseSolrClient() { 
    	if (solrClient==null)
    		solrClient = newSolrClient(baseUrl);    	
        return solrClient;
    }

    /**
     * 获取solrClient.
     * @return SolrClient
     */
    public static SolrClient newSolrClient(String zkHost,String defaultCollection) {
//        String zkHost = ConfigSupport.readValue("zkHost"); //获取zookeeper主机
//        String defaultCollection = ConfigSupport.readValue("solr.collection"); //获取solrCloud集合
    	log.info("构造SolrClient，zkHsot[" + zkHost + "]" + ",collection[" + defaultCollection + "]");
//        System.out.println("构造SolrClient，zkHsot[" + zkHost + "]"  + ",collection[" + defaultCollection + "]");
        CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost, httpClient);
        cloudSolrClient.setZkConnectTimeout(100000);
        cloudSolrClient.setDefaultCollection(defaultCollection);        
        return cloudSolrClient;
    }

    /**
     * 获取solrClient.
     * @return SolrClient
     */
    public static SolrClient newSolrClient(String baseSolrUrl) {
        System.out.println("构造SolrClient，baseSolrUrl[" + baseSolrUrl + "]");        
        HttpSolrClient client= new HttpSolrClient(baseSolrUrl, httpClient);
//        client.setMaxTotalConnections(maxConnections);
        return client;
    }
    
    /**
     * 获取httpclient 做为solr发送请求的客户端类.
     */
    private static void newHttpClient() {
        ModifiableSolrParams mdp = new ModifiableSolrParams();
        mdp.set(HttpClientUtil.PROP_MAX_CONNECTIONS, maxConnections);
        mdp.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, maxConnectionsPerHost);
        mdp.set(HttpClientUtil.PROP_FOLLOW_REDIRECTS, false);
        mdp.set(HttpClientUtil.PROP_CONNECTION_TIMEOUT, 20000);
        httpClient = HttpClientUtil.createClient(mdp);
    }
    
    /**
     * 设置solr访问的索引集合名称
     * @param collectionName
     */
    public static void setDefaultCollection(String collection){
    	log.info("set solr query collection : " + collection);
    	setCollection(collection);
		((CloudSolrClient) solrClient).setDefaultCollection(collection);
	}
        
    /**
     * 设置solr访问的索引集合名称
     * @param collection
     */
    public static void setCollection(String collection) {
		SolrUtils.collection = collection;
	}

	/**
     * 将查询到的solrDocument转换为实体对象.
     * @param doc   查询到的solrDocument
     * @param clazz 对象类类型
     * @param <T>   类类型参数
     * @return 返回实体对象
     * @throws IllegalAccessException IllegalAccessException
     * @throws InstantiationException InstantiationException
     */
    public static <T> T convertDoc2Bean(final SolrDocument doc, final Class<T> clazz) throws IllegalAccessException, InstantiationException {
        if (doc == null || clazz == null) return null;
        Field[] fields = clazz.getDeclaredFields(); //获取类所有定义的字段
        if (fields == null || fields.length == 0) return null;
        T t = clazz.newInstance(); //获取类的对象
        for (Field field : fields) {
            field.setAccessible(true); //私有变量可读写
            Object val = doc.get(field.getName()); //在doc中搜询键为类定义字段的值
            if (val == null) continue;
            try {
                field.set(t, val); //设置属性值
            } catch (IllegalAccessException e) {
            	log.warn("赋值失败:" + clazz.getSimpleName() + "." + field.getName() + ",val=" + val);
            }
            field.setAccessible(false);
        }
        return t;
    }
    
    /**
	 * 将实体对象转换为文档类
	 * @param record
	 * @param clazz
	 * @return
	 */
	public static SolrInputDocument convertBeanToDoc(final Object o) {
		SolrInputDocument doc=new SolrInputDocument();
		Field[] fields = o.getClass().getDeclaredFields();//取出所有字段
		for (Field field : fields) {
			String name = field.getName();
			try {
		        doc.setField(name,BeanUtils.getProperty(o, field.getName()));//获取字段值
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e){
				e.printStackTrace();
			}
		}
		return doc;
	}
	
    /**
     * 将实体对象转换为文档类,只是有@Target的對象
     * @param o
     * @return
     */
    public static SolrInputDocument convertTargetBeanToDoc(final Object o){    	
    	String columnName = null;
		SolrInputDocument doc=new SolrInputDocument();
		Field[] fields = o.getClass().getDeclaredFields();//取出所有字段
		for (Field field : fields) {
			if (field.isAnnotationPresent(DocColumn.class)) {//在对象字段上加了注解才有效匹配
				columnName = field.getAnnotation(DocColumn.class).name();//取出定义的名称
			} else {
				continue;
			}
			if (columnName==null || columnName.trim().length()==0){
				columnName = field.getName();
			}
			try {
		        doc.setField(columnName,BeanUtils.getProperty(o, field.getName()));//获取字段值
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e){
				e.printStackTrace();
			}
		}
		return doc;
    }
}
